﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xunit;

namespace MetaSharp.Transformation.Tests.Patterns
{
    public class EmptyStreamTests
    {
        private IStream stream;
        public EmptyStreamTests()
        {
            stream = new MetaSharp.Transformation.Stream();
        }

        [Fact]
        public void IsEmpty()
        {
            Assert.True(stream.IsEmpty);
        }

        [Fact]
        public void CurrentThows()
        {
            Assert.Throws<InvalidOperationException>(() => stream.Current);
        }

        [Fact]
        public void NextThrows()
        {
            Assert.Throws<InvalidOperationException>(() => stream.Next());
        }

        [Fact]
        public void IntoThrows()
        {
            Assert.Throws<InvalidOperationException>(() => stream.Into());
        }
    }

    public class StreamWithInnerArray
    {
        private IStream stream;

        public StreamWithInnerArray()
        {
            stream = new MetaSharp.Transformation.Stream(new[] {
                new [] { 7 },
            });
        }

        [Fact]
        public void CanStepInto()
        {
            var next = stream.Next();
            var into = next.Into();
            var first = into.Next();
            Assert.Equal(7, first.Current);
        }
    }

    public class StreamWithSingleItemTests
    {
        private IStream stream;
        public StreamWithSingleItemTests()
        {
            stream = new MetaSharp.Transformation.Stream(7);
        }

        [Fact]
        public void IsNotEmpty()
        {
            Assert.False(stream.IsEmpty);
        }

        [Fact]
        public void CurrentThrowsBeforeNext()
        {
            Assert.Throws<InvalidOperationException>(() => stream.Current);
        }

        [Fact]
        public void NextDoesNotThrow()
        {
            stream.Next();
        }

        [Fact]
        public void NextIsEmpty()
        {
            var next = stream.Next();
            Assert.True(next.IsEmpty);
        }

        [Fact]
        public void NextHasCurrent()
        {
            var next = stream.Next();
            Assert.Equal(7, next.Current);
        }

        [Fact]
        public void MustNotProvideNullItems()
        {
            Assert.Throws<ArgumentNullException>(() => new MetaSharp.Transformation.Stream(null));
        }

        [Fact]
        public void CanContainNull()
        {
            var stream = new MetaSharp.Transformation.Stream(new object[] { null });
            var next = stream.Next();
            Assert.Null(next.Current);
        }
    }

    public class StreamWithMultipleItems
    {
        private IStream stream;
        public StreamWithMultipleItems()
        {
            stream = new MetaSharp.Transformation.Stream(7, 11);
        }

        [Fact]
        public void NextItemIsntEmpty()
        {
            var next = stream.Next();
            Assert.False(next.IsEmpty);
        }
    }
}
